// #include <iostream>
// #include <string>
// #include <cstring>
// #include <unistd.h>
// #include <sys/types.h>
// #include <sys/socket.h>
// #include <arpa/inet.h>
// #include <netinet/in.h>

// int main(int argc, char *argv[])
// {
//     if (argc != 3)
//     {
//         std::cerr << "Uasge " << argv[0] << " ip port" << std::endl;
//         exit(1);
//     }

//     // 获取ip 和 port
//     std::string ip = argv[1];
//     uint16_t port = std::stoi(argv[2]);

//     // 创建 upd-socket
//     int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
//     if (socket < 0)
//     {
//         std::cerr << "socket error" << std::endl;
//         exit(2);
//     }

//     // 从创建存储服务器的 ip 和 port 的结构体 struct sockaddr_in
//     struct sockaddr_in server;
//     bzero(&server, sizeof(server));                 // 初始化
//     server.sin_family = AF_INET;                    // 标识网络套接
//     server.sin_port = htons(port);                  // 转为网络序列
//     server.sin_addr.s_addr = inet_addr(ip.c_str()); // 将字符串的 ip 转换为字4字节的整数

//     while (true)
//     {
//         // 客户需要请求的消息
//         std::string message;
//         std::cout << "Please Enter@ " << std::endl;
//         std::getline(std::cin, message);

//         // 发送给服务器 请求
//         int n = ::sendto(socket,message.c_str(), message.size(), 0, (struct sockaddr*)&server, sizeof(server));
//         if (n > 0)
//         {
//             // 记录 响应服务器 的 ip 和 port
//             struct sockaddr_in peer;
//             socklen_t len = sizeof(peer);
//             // 接受消息
//             char buffer[1024];
//             int m = ::recvfrom(socket, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&peer, &len);
//             if (m > 0)
//             {
//                 // 最后一个字符后面补 \0
//                 buffer[m] = 0;
//                 std::cout << buffer << std::endl;
//             }
//             else
//             {
//                 std::cerr << "recvfrom error" << std::endl;
//                 break;
//             }
//         }
//         else
//         {
//             std::cerr << "bind error" << std::endl;
//             break;
//         }
//     }

//     return 0;
// }

#include "UdpClient.hpp"
#include "Thread.hpp"
#include <memory>

using namespace ThreadModule;

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        std::cerr << "Uasge " << argv[0] << " ip port" << std::endl;
        exit(1);
    }

    // 获取ip 和 port
    std::string ip = argv[1];
    uint16_t port = std::stoi(argv[2]);

    // std::cout << ip << " + " << port << std::endl;

    // UdpClient uct(ip, port);
    std::unique_ptr<UdpClient> uct = std::make_unique<UdpClient>(ip, port);

    Thread recver("recver-thread", std::bind(&UdpClient::RecvMessage, uct.get(), std::placeholders::_1));
    Thread sender("sender-thread", std::bind(&UdpClient::SendMessage, uct.get(), std::placeholders::_1));

    recver.start();
    sender.start();

    recver.join();
    sender.join();
    return 0;
}